关键字typename是在C++标准化过程中引入的，目的是说明模板内的标识符是类型。比如下面的例子:

\begin{lstlisting}[style=styleCXX]
template<typename T>
class MyClass {
	public:
	...
	void foo() {
		typename T::SubType* ptr;
	}
};
\end{lstlisting}

这里，第二个typename用于说明SubType是在类T中定义的类型。因此，ptr是指向类型T::SubType的指针。

若没有typename, SubType将假定为非类型成员(例如，静态数据成员或枚举数常量)。因此，表达式

\begin{lstlisting}[style=styleCXX]
T::SubType* ptr
\end{lstlisting}

表示的是类T的静态SubType成员与ptr的乘积，这不是一个错误，因为对于MyClass<>的某些实例化，这可能有效。

当模板参数是类型时，必须使用typename。这将在第13.3.2节中详细讨论。

typename的一种应用是在泛型代码中声明标准容器的迭代器:

\noindent
\textit{basics/printcoll.hpp}
\begin{lstlisting}[style=styleCXX]
#include <iostream>

// print elements of an STL container
template<typename T>
void printcoll (T const& coll)
{
	typename T::const_iterator pos; // iterator to iterate over coll
	typename T::const_iterator end(coll.end()); // end position
	for (pos=coll.begin(); pos!=end; ++pos) {
		std::cout << *pos << ' ';
	}
	std::cout << '\n';
}
\end{lstlisting}

这个函数模板中，调用参数是一个T类型的标准容器。要遍历容器的所有元素，需要使用容器的迭代器类型，在每个标准容器类中声明为const\_iterator的类型:

\begin{lstlisting}[style=styleCXX]
class stlcontainer {
	public:
	using iterator = ...; // iterator for read/write access
	using const_iterator = ...; // iterator for read access
	...
};
\end{lstlisting}

因此，要访问模板类型T的const\_iterator类型，必须用typename进行限定:

\begin{lstlisting}[style=styleCXX]
typename T::const_iterator pos;
\end{lstlisting}

有关在C++17前需要typename的更多细节，请参阅第13.3.2节。注意，C++20在许多常见情况下可能会删除对typename的需要(请参阅第17.1节了解详细信息)。











